package kit.docker.file;

import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;
import kit.docker.exception.BaseException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class FileKit {

    /**
     * 复制文件
     *
     * @param sourcePath 源文件路径
     * @param destPath   目标路径
     */
    public static void copyFile(String sourcePath, String destPath) {
        File source = new File(sourcePath);
        if (!source.exists()) {
            throw new RuntimeException("源文件不存在");
        }
        if (!source.isFile()) {
            throw new RuntimeException("源文件类型错误");
        }
        File dest = new File(destPath);
        File temp = new File(destPath.substring(0, destPath.lastIndexOf(File.separator)));
        createDirectory(temp);

        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } catch (Exception e) {
            throw new RuntimeException("文件读取错误");
        } finally {
            try {
                inputChannel.close();
                outputChannel.close();
            } catch (Exception e) {
                throw new RuntimeException("文件写入错误");
            }

        }

    }

    /**
     * 转移文件，并重命名
     *
     * @param sourcePath  原文件路径
     * @param newFilePath 目标文件路径,包含文件名称
     */
    public static void renameTo(String sourcePath, String newFilePath) {
        renameTo(new File(sourcePath), newFilePath);
    }

    /**
     * 转移文件，并重命名
     *
     * @param file        原文件
     * @param newFilePath 目标文件路径,包含文件名称
     */
    public static void renameTo(File file, String newFilePath) {
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
        if (!file.isFile()) {
            throw new RuntimeException("未知文件类型");
        }

        File temp = new File(newFilePath.substring(0, newFilePath.lastIndexOf(File.separator)));
        createDirectory(temp);
        file.renameTo(new File(newFilePath));
        if (file.exists()) {
            deleteFile(file);
        }
    }

    private static void createDirectory(File file) {
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public static void deleteFile(List<UploadFile> files) {
        for (UploadFile file : files) {
            deleteFile(file);
        }
    }

    public static void deleteFile(UploadFile file) {
        deleteFile(file.getFile());
    }

    /**
     * 删除文件
     *
     * @param filePath 待删除的文件路径
     */
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        deleteFile(file);
    }

    public static void deleteFile(File file) {
        if (!StrKit.notNull(file) || !file.exists()) {
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                deleteFile(files[i]);
            }
        }
        if (!file.delete()) {
            System.gc();
            file.delete();
        }
    }

    public static String getRealName(File file) {
        String name = file.getName();
        return getRealName(name);
    }

    public static String getRealName(String fileName) {
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    public static boolean checkFile(File file) {
        return checkFile(file, null, new String[0]);
    }

    public static boolean checkFile(File file, Integer size) {
        return checkFile(file, size, new String[0]);
    }

    public static boolean checkFile(File file, String... extNames) {
        return checkFile(file, null, extNames);
    }

    public static boolean checkFile(File file, Integer size, String... extNames) {
        if (!StrKit.notNull(file)) {
            deleteFile(file);
            throw new BaseException("上传文件为空");
        }
        String fileName = file.getName();
        String extName = getExtName(fileName);
        if (StrKit.isBlank(extName)) {
            deleteFile(file);
            throw new BaseException("文件类型获取失败");
        }
        if (StrKit.notBlank(extNames) && extNames.length > 0) {
            if (!Arrays.asList(extNames).contains(extName)) {
                deleteFile(file);
                throw new BaseException("不支持的上传类型");
            }
        }
        if (StrKit.notNull(size) && size > 0) {
            if (file.length() > (size * 1024)) {
                deleteFile(file);
                throw new BaseException("文件大小超出" + size + "k");
            }
        }
        return true;
    }

    /**
     * 获取文件后缀名
     */
    public static String getExtName(String fileName) {
        int index = fileName.lastIndexOf('.');
        if (index != -1 && (index + 1) < fileName.length()) {
            return fileName.substring(index + 1);
        }
        return null;
    }

    /**
     * 获取文件名称含格式
     */
    public static String getFileNameExt(String filePath) {
        File file = new File(filePath);
        return file.getName();
    }

    /**
     * 获取文件名称不含格式
     */
    public static String getFileName(String filePath) {
        String fileName = getFileNameExt(filePath);
        String extName = getExtName(fileName);
        if (StrKit.isBlank(extName)) {
            return fileName;
        }
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    public static String getBaseUploadPath() {
        String path = PathKit.getWebRootPath() + File.separator + "upload";
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        return path;
    }

    public static String getBaseDownloadPath() {
        String path = PathKit.getWebRootPath() + File.separator + "download";
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        return path;
    }

    /**
     * 根据路径获取文件夹下的所有文件列表
     *
     * @param filePath
     */
    public static List<Record> list(String filePath) {
        List<Record> fileList = new ArrayList<>();
        List<Record> dirList = new ArrayList<>();
        File file = new File(filePath);
        try {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files == null) {
                    return fileList;
                }
                Arrays.sort(files, Comparator.comparing(File::getName));
                Record record;
                for (File fileI : files) {
                    record = new Record();
                    record.set("file_type", "1"); //1-文件，2-文件夹
                    record.set("file_path", fileI.getPath());
                    record.set("file_name", fileI.getName());
                    if (fileI.isDirectory()) {
                        record.set("file_type", "2");
                        dirList.add(record);
                        continue;
                    }
                    fileList.add(record);
                }
            } else {
                Record record = new Record();
                record.set("file_type", "1"); //1-文件，2-文件夹
                record.set("file_path", file.getPath());
                record.set("file_name", file.getName());
                fileList.add(record);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        dirList.addAll(fileList);
        return dirList;
    }

}
